﻿// Tests the vector datastructure.
//
// Copyright (C) 2012 M. de Wolde
//
// This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General Public License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// 2012-06-15 MIWO Created.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Text;
using System.Threading;
using Lemody.Glu;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Lemody.GluTest {

/// <summary>Tests the vector datastructure.</summary>
[TestClass]
public class VectorTest
{
    // This test class uses "int" for vector indexes and vector counts, as expected by the Vector class. This test class
    // uses "Int32" or "Int64" when an int or long is intended, regardless whether testing the Vector or LongVector
    // class. This eases to recreate the LongVector test from the Vector test.

    // Constants.
    // -----------------------------------------------------------------------------------------------------------------

    /// <summary>Minimum duration of performance tests, in s.</summary>
    private const Int32 DurationPerformanceTests = 1;

    // Fields.
    // -----------------------------------------------------------------------------------------------------------------

    /// <summary>Int element available for tests.</summary>
    private Int32 _int32Element;

    // Tests and test support.
    // -----------------------------------------------------------------------------------------------------------------

    /// <summary>Returns a random number generator for use in the tests.</summary>
    /// <remarks>
    ///     The generator is randomized such that tests will be different from run to run. The method captures and
    ///     reports the used seed, allowing to repeat a failed test by creating a new Random with the captured seed.
    ///     Do this by replacing Random rng = Rng(MethodInfo.GetCurrentMethod()); by for example Random rng = new
    ///     Random(1200957226);.
    /// </remarks>
    /// <param name="method">I: Test method.</param>
    private Random Rng(MethodBase method)
    {
        Int32 seed = new Random().Next();
        Random rng = new Random(seed);
        Trace.WriteLine(string.Format("Test {0}: random number generator seed: {1}", method.Name, seed));
        return rng;
    }

    /// <summary>Performs random inserts, deletes and other operations to test the vector as a generic collection.</summary>
    [TestMethod]
    public void VectorAsGenericCollection()
    {
        // Create the vector collection under test and create a generic list as reference collection.
        var vector = new Vector<Int32>();
        var list = new List<Int32>();
        const Int32 ValueRange = 1000;
        const Int32 CountRange = 100;
        Random rng = Rng(MethodInfo.GetCurrentMethod());

        // Populate the collections, whilst also performing updates and deletes.
        {
            int count = rng.Next(CountRange);
            for (int i = 0; i != count; i++)
            {
                switch (rng.Next(4))
                {
                    case 0: // Add.
                    {
                        Int32 element = rng.Next(ValueRange);
                        vector.Add(element);
                        list.Add(element);
                        break;
                    }
                    case 1: // Insert.
                    {
                        int index = rng.Next(list.Count + 1);
                        Int32 element = rng.Next(ValueRange);
                        if (rng.Next(2) == 0)
                        {
                            vector.Insert(index, element);
                        }
                        else
                        {
                            VectorNode<Int32> node = vector.InsertAt(index, element);
                            Assert.AreEqual(element, node.Element);
                            Assert.AreEqual(index, node.GetIndex());
                        }
                        list.Insert(index, element);
                        break;
                    }
                    case 2: // Update.
                    {
                        if (list.Count != 0)
                        {
                            int index = rng.Next(list.Count);
                            Int32 element = rng.Next(ValueRange);
                            vector[index] = element;
                            list[index] = element;
                        }
                        break;
                    }
                    case 3: // Remove.
                    {
                        if (list.Count != 0)
                        {
                            int index = rng.Next(list.Count);
                            vector.RemoveAt(index);
                            list.RemoveAt(index);
                        }
                        break;
                    }
                    default:
                    {
                        throw new Exception();
                    }
                }
            }
        }

        // Test the consistency and internal balancing of the vector.
        Assert.AreEqual(true, vector.GetConsistency());

        // Compare the vector to the reference list.
        {
            Assert.AreEqual(list.Count, vector.Count);
            for (int i = 0; i != list.Count; i++)
            {
                Assert.AreEqual(list[i], vector[i]);
            }
        }

        // Enumerate the vector using a simple enumeration.
        {
            int i = 0;
            foreach (Int32 element in vector)
            {
                Assert.AreEqual(list[i], element);
                i++;
            }
            Assert.AreEqual(list.Count, i);
        }

        // Enumerate the vector using an enumerator.
        {
            var listEnumerator = list.GetEnumerator();
            var vectorEnumerator = vector.GetEnumerator();
            for (int i = 0; i != list.Count; i++)
            {
                Assert.AreEqual(true, listEnumerator.MoveNext());
                Assert.AreEqual(true, vectorEnumerator.MoveNext());
                Assert.AreEqual(listEnumerator.Current, vectorEnumerator.Current);
            }
            Assert.AreEqual(false, listEnumerator.MoveNext());
            Assert.AreEqual(false, vectorEnumerator.MoveNext());
        }

        // Enumerate the fictive elements just before and after the vector.
        {
            VectorEnumerator<Int32> enumerator = vector.GetVectorEnumerator();
            if (list.Count == 0)
            {
                Assert.AreEqual(false, enumerator.MoveNext());
            }
            else
            {
                Assert.AreEqual(true, enumerator.MoveNext());
                Assert.AreEqual(vector[0], enumerator.Current);
                Assert.AreEqual(false, enumerator.MovePrevious());
                Assert.AreEqual(true, enumerator.MoveNext());
                Assert.AreEqual(vector[0], enumerator.Current);
                while (enumerator.MoveNext())
                {
                    //
                }
                Assert.AreEqual(true, enumerator.MovePrevious());
                Assert.AreEqual(vector[list.Count - 1], enumerator.Current);
                Assert.AreEqual(false, enumerator.MoveNext());
                Assert.AreEqual(true, enumerator.MovePrevious());
                Assert.AreEqual(vector[list.Count - 1], enumerator.Current);
            }
        }

        // Update a vector element through a vector node.
        if (list.Count != 0)
        {
            for (Int32 test = 0; test != 10; test++)
            {
                int index = rng.Next(list.Count);
                Int32 element = rng.Next(ValueRange);
                VectorNode<Int32> node = vector.GetNode(index);
                list[index] = element;
                node.Element = element;
                Assert.AreEqual(element, node.Element);
                Assert.AreEqual(element, vector[index]);
            }
        }

        // Test the index returned for a node.
        {
            for (int index = 0; index != vector.Count; index++)
            {
                Assert.AreEqual(index, vector.GetNode(index).GetIndex());
            }
        }

        // Copy the vector.
        {
            var vector2 = new Vector<Int32>(vector);
            Assert.AreEqual(vector.Count, vector2.Count);
            for (int i = 0; i != vector.Count; i++)
            {
                Assert.AreEqual(vector[i], vector2[i]);
            }
            Assert.AreEqual(true, vector2.GetConsistency());
        }

        // Perform a final compare of the vector and the reference list.
        {
            Assert.AreEqual(list.Count, vector.Count);
            for (int i = 0; i != list.Count; i++)
            {
                Assert.AreEqual(list[i], vector[i]);
            }
        }

        // Clear.
        {
            vector.Clear();
            list.Clear();
            Assert.AreEqual(0, vector.Count);
            Assert.AreEqual(true, vector.GetConsistency());
        }
    }

    /// <summary>Test the vector as an ICollection of T.</summary>
    [TestMethod]
    public void VectorAsICollection()
    {
        // Vector of Int32.
        {
            ICollection<Int32> vector = new Vector<Int32>();
            Assert.AreEqual(0, vector.Count);
            Assert.AreEqual(false, vector.IsReadOnly);
            vector.Add(1);
            vector.Add(2);
            vector.Add(3);
            Assert.AreEqual(3, vector.Count);
            vector.Clear();
            Assert.AreEqual(0, vector.Count);
            vector.Add(1);
            vector.Add(2);
            vector.Add(3);
            Assert.AreEqual(false, vector.Contains(0));
            Assert.AreEqual(true, vector.Contains(1));
            Assert.AreEqual(true, vector.Contains(2));
            Assert.AreEqual(true, vector.Contains(3));
            Assert.AreEqual(false, vector.Contains(4));
            var array = new Int32[10];
            vector.CopyTo(array, 0);
            Assert.AreEqual(1, array[0]);
            Assert.AreEqual(2, array[1]);
            Assert.AreEqual(3, array[2]);
            Assert.AreEqual(0, array[3]);
            vector.CopyTo(array, 7);
            Assert.AreEqual(1, array[0]);
            Assert.AreEqual(2, array[1]);
            Assert.AreEqual(3, array[2]);
            Assert.AreEqual(0, array[3]);
            Assert.AreEqual(0, array[6]);
            Assert.AreEqual(1, array[7]);
            Assert.AreEqual(2, array[8]);
            Assert.AreEqual(3, array[9]);
            {
                IEnumerator i = vector.GetEnumerator();
                Assert.AreEqual(true, i.MoveNext());
                Assert.AreEqual(1, i.Current);
                Assert.AreEqual(true, i.MoveNext());
                Assert.AreEqual(2, i.Current);
                Assert.AreEqual(true, i.MoveNext());
                Assert.AreEqual(3, i.Current);
                Assert.AreEqual(false, i.MoveNext());
            }
            {
                IEnumerator<Int32> i = vector.GetEnumerator();
                Assert.AreEqual(true, i.MoveNext());
                Assert.AreEqual(1, i.Current);
                Assert.AreEqual(true, i.MoveNext());
                Assert.AreEqual(2, i.Current);
                Assert.AreEqual(true, i.MoveNext());
                Assert.AreEqual(3, i.Current);
                Assert.AreEqual(false, i.MoveNext());
            }
            Assert.AreEqual(false, vector.Remove(0));
            Assert.AreEqual(true, vector.Remove(2));
            Assert.AreEqual(false, vector.Remove(2));
            Assert.AreEqual(true, vector.Contains(1));
            Assert.AreEqual(false, vector.Contains(2));
            Assert.AreEqual(true, vector.Contains(3));
            Assert.AreEqual(true, vector.Remove(1));
            Assert.AreEqual(false, vector.Contains(1));
            Assert.AreEqual(true, vector.Contains(3));
            Assert.AreEqual(1, vector.Count);
            Assert.AreEqual(true, vector.Remove(3));
            Assert.AreEqual(0, vector.Count);
        }
        // Vector of string.
        {
            ICollection<string> vector = new Vector<string>();
            Assert.AreEqual(0, vector.Count);
            Assert.AreEqual(false, vector.IsReadOnly);
            vector.Add("a");
            vector.Add("b");
            vector.Add("c");
            Assert.AreEqual(3, vector.Count);
            vector.Clear();
            Assert.AreEqual(0, vector.Count);
            vector.Add("a");
            vector.Add("b");
            vector.Add("c");
            Assert.AreEqual(false, vector.Contains(" "));
            Assert.AreEqual(true, vector.Contains("a"));
            Assert.AreEqual(true, vector.Contains("b"));
            Assert.AreEqual(true, vector.Contains("c"));
            Assert.AreEqual(false, vector.Contains("d"));
            var array = new string[10];
            vector.CopyTo(array, 0);
            Assert.AreEqual("a", array[0]);
            Assert.AreEqual("b", array[1]);
            Assert.AreEqual("c", array[2]);
            Assert.AreEqual(null, array[3]);
            vector.CopyTo(array, 7);
            Assert.AreEqual("a", array[0]);
            Assert.AreEqual("b", array[1]);
            Assert.AreEqual("c", array[2]);
            Assert.AreEqual(null, array[3]);
            Assert.AreEqual(null, array[6]);
            Assert.AreEqual("a", array[7]);
            Assert.AreEqual("b", array[8]);
            Assert.AreEqual("c", array[9]);
            {
                IEnumerator i = vector.GetEnumerator();
                Assert.AreEqual(true, i.MoveNext());
                Assert.AreEqual("a", i.Current);
                Assert.AreEqual(true, i.MoveNext());
                Assert.AreEqual("b", i.Current);
                Assert.AreEqual(true, i.MoveNext());
                Assert.AreEqual("c", i.Current);
                Assert.AreEqual(false, i.MoveNext());
            }
            {
                IEnumerator<string> i = vector.GetEnumerator();
                Assert.AreEqual(true, i.MoveNext());
                Assert.AreEqual("a", i.Current);
                Assert.AreEqual(true, i.MoveNext());
                Assert.AreEqual("b", i.Current);
                Assert.AreEqual(true, i.MoveNext());
                Assert.AreEqual("c", i.Current);
                Assert.AreEqual(false, i.MoveNext());
            }
            Assert.AreEqual(false, vector.Remove(" "));
            Assert.AreEqual(true, vector.Remove("b"));
            Assert.AreEqual(false, vector.Remove("b"));
            Assert.AreEqual(true, vector.Contains("a"));
            Assert.AreEqual(false, vector.Contains("b"));
            Assert.AreEqual(true, vector.Contains("c"));
            Assert.AreEqual(true, vector.Remove("a"));
            Assert.AreEqual(false, vector.Contains("a"));
            Assert.AreEqual(true, vector.Contains("c"));
            Assert.AreEqual(1, vector.Count);
            Assert.AreEqual(true, vector.Remove("c"));
            Assert.AreEqual(0, vector.Count);
        }
    }

    /// <summary>Converter delegate used in a test.</summary>
    /// <param name="element">I: Element to convert.</param>
    /// <returns>Converted element.</returns>
    private static string IntToStringConverter(Int32 element)
    {
        return element.ToString();
    }

    /// <summary>Predicate used for the test.</summary>
    /// <param name="element">I: Element to compare.</param>
    private static bool Is3(Int32 element)
    {
        return element == 3;
    }

    /// <summary>Predicate used for the test.</summary>
    /// <param name="element">I: Element to compare.</param>
    private static bool IsC(string element)
    {
        return element == "C";
    }

    /// <summary>Action delegate used for the test.</summary>
    /// <param name="element">I: Element to sum.</param>
    private void Sum(Int32 element)
    {
        _int32Element += element;
    }

    /// <summary>Tests the support added to the vector for symmetry with the generic list of T.</summary>
    [TestMethod]
    public void VectorAsListOfT()
    {
        Random rng = Rng(MethodInfo.GetCurrentMethod());

        // Read-only wrapper.
        {
            var vector = new Vector<Int32>();
            vector.Add(1);
            vector[0] = 2;
            Assert.AreEqual(2, vector[0]);
            var readOnlyVector = vector.AsReadOnly();
            Assert.AreEqual(2, vector[0]);
            vector[0] = 3;
            Assert.AreEqual(3, vector[0]);
            Assert.AreEqual(3, readOnlyVector[0]);
            Assert.AreEqual(true, vector.GetConsistency());
        }

        // Binary search.
        for (Int32 test = 0; test != 10; test++)
        {
            // Prepare values.
            const Int32 ValueRange = 5;
            const Int32 CountRange = 50;
            const string FormatString = "{0:000}";
            var intList = new List<Int32>();
            var stringList = new List<string>();
            var int32Vector = new Vector<Int32>();
            var stringVector = new Vector<string>();
            int count = rng.Next(CountRange);
            {
                Int32 intValue = 1;
                for (int i = 0; i != count; i++)
                {
                    intValue += rng.Next(ValueRange);
                    intList.Add(intValue);
                    int32Vector.Add(intValue);
                    string stringValue = string.Format(FormatString, intValue);
                    stringList.Add(stringValue);
                    stringVector.Add(stringValue);
                }
            }

            // Search existing values.
            for (int i = 0; i != count; i++)
            {
                Int32 intValue = intList[i];
                int listIndex = intList.BinarySearch(intValue);
                int vectorIndex = int32Vector.BinarySearch(intValue);
                Assert.AreEqual(true, vectorIndex >= 0 && vectorIndex < count);
                Assert.AreEqual(intList[listIndex], int32Vector[vectorIndex]);
                string stringValue = string.Format(FormatString, intValue);
                listIndex = stringList.BinarySearch(stringValue);
                vectorIndex = stringVector.BinarySearch(stringValue);
                Assert.AreEqual(true, vectorIndex >= 0 && vectorIndex < count);
                Assert.AreEqual(stringList[listIndex], stringVector[vectorIndex]);
            }

            // Search non-existing values.
            if (count == 0)
            {
                Int32 intValue = rng.Next(ValueRange);
                Assert.AreEqual(~0, int32Vector.BinarySearch(intValue));
                string stringValue = string.Format(FormatString, intValue);
                Assert.AreEqual(~0, stringVector.BinarySearch(stringValue));
            }
            else
            {
                Int32 intValue = intList[0] - 1;
                while (intValue <= intList[count - 1] + 1)
                {
                    if (!intList.Contains(intValue))
                    {
                        Assert.AreEqual(intList.BinarySearch(intValue), int32Vector.BinarySearch(intValue));
                        string stringValue = string.Format(FormatString, intValue);
                        Assert.AreEqual(stringList.BinarySearch(stringValue), stringVector.BinarySearch(stringValue));
                    }
                    intValue++;
                }
            }

            // Test the consistency and internal balancing of the vector.
            Assert.AreEqual(true, int32Vector.GetConsistency());
            Assert.AreEqual(true, stringVector.GetConsistency());

            // Search a range.
            for (Int32 i = 0; i != 10; i++)
            {
                int rangeIndex = count == 0? 0: rng.Next(count);
                int rangeCount = count - rangeIndex == 0? 0: rng.Next(count - rangeIndex);
                Int32 intValue = count == 0? rng.Next(ValueRange): rng.Next(intList[count - 1] + ValueRange);
                int index = intList.BinarySearch(rangeIndex, rangeCount, intValue, Comparer<Int32>.Default);
                if (index < 0)
                {
                    Assert.AreEqual(~index, ~int32Vector.BinarySearch(rangeIndex, rangeCount, intValue, Comparer<Int32>.Default));
                }
                else
                {
                    Assert.AreEqual(intList[index], int32Vector[index]);
                }
            }
        }

        // Convert all.
        {
            var int32Vector = new Vector<Int32>();
            int32Vector.Add(1);
            int32Vector.Add(2);
            int32Vector.Add(3);
            Vector<string> stringVector = int32Vector.ConvertAll<string>(IntToStringConverter);
            Assert.AreEqual(3, stringVector.Count);
            Assert.AreEqual("1", stringVector[0]);
            Assert.AreEqual("2", stringVector[1]);
            Assert.AreEqual("3", stringVector[2]);
        }

        // Copy to array.
        for (Int32 test = 0; test != 10; test++)
        {
            int count = rng.Next(5);
            var int32Vector = new Vector<Int32>();
            var stringVector = new Vector<string>();
            for (Int32 i = 1; i <= count; i++)
            {
                int32Vector.Add(i);
                stringVector.Add(i.ToString());
            }
            Int32[] intArray = new Int32[count];
            string[] stringArray = new string[count];
            int32Vector.CopyTo(intArray);
            stringVector.CopyTo(stringArray);
            for (int i = 0; i != count; i++)
            {
                Assert.AreEqual(int32Vector[i], intArray[i]);
                Assert.AreEqual(stringVector[i], stringArray[i]);
            }
            if (count != 0)
            {
                count--;
                int32Vector.RemoveAt(count);
                stringVector.RemoveAt(count);
                int32Vector.CopyTo(intArray, 1);
                stringVector.CopyTo(stringArray, 1);
                Assert.AreEqual(1, intArray[0]);
                Assert.AreEqual("1", stringArray[0]);
                for (int i = 0; i != count; i++)
                {
                    Assert.AreEqual(int32Vector[i], intArray[1 + i]);
                    Assert.AreEqual(stringVector[i], stringArray[1 + i]);
                }
                if (count != 0)
                {
                    for (Int32 i = 0; i != count; i++)
                    {
                        int32Vector[i] = i;
                        stringVector[i] = i.ToString();
                        intArray[i] = i;
                        stringArray[i] = i.ToString();
                    }
                    Int32 element = rng.Next();
                    int fromIndex = rng.Next(count);
                    int32Vector[fromIndex] = element;
                    stringVector[fromIndex] = element.ToString();
                    int toIndex = rng.Next(count);
                    int32Vector.CopyTo(fromIndex, intArray, toIndex, 1);
                    stringVector.CopyTo(fromIndex, stringArray, toIndex, 1);
                    for (int i = 0; i != count; i++)
                    {
                        if (i == toIndex)
                        {
                            Assert.AreEqual(element, intArray[i]);
                            Assert.AreEqual(element.ToString(), stringArray[i]);
                        }
                        else
                        {
                            Assert.AreEqual(i, intArray[i]);
                            Assert.AreEqual(i.ToString(), stringArray[i]);
                        }
                    }
                }
            }
        }

        // Vector equality.
        {
            var vector = new Vector<Int32>();
            Assert.AreEqual(false, vector.Equals(null));
            var vector1 = new Vector<Int32>();
            Assert.AreEqual(true, vector.Equals(vector1));
            vector1.Add(1);
            Assert.AreEqual(false, vector.Equals(vector1));
            vector.Add(1);
            Assert.AreEqual(true, vector.Equals(vector1));
            vector[0] = 2;
            Assert.AreEqual(false, vector.Equals(vector1));
            var vector2 = new Vector<Int64>();
            Assert.AreEqual(false, vector.Equals(vector2));
            vector2.Add(2);
            Assert.AreEqual(false, vector.Equals(vector2));
            vector.Clear();
            vector2.Clear();
            Assert.AreEqual(false, vector.Equals(vector2));
        }
        {
            var vector = new Vector<string>();
            Assert.AreEqual(false, vector.Equals(null));
            var vector1 = new Vector<string>();
            Assert.AreEqual(true, vector.Equals(vector1));
            vector1.Add("a");
            Assert.AreEqual(false, vector.Equals(vector1));
            vector.Add("a");
            Assert.AreEqual(true, vector.Equals(vector1));
            vector[0] = "A";
            Assert.AreEqual(false, vector.Equals(vector1));
            var vector2 = new Vector<Int64>();
            Assert.AreEqual(false, vector.Equals(vector2));
            vector[0] = "2";
            vector2.Add(2);
            Assert.AreEqual(false, vector.Equals(vector2));
            vector.Clear();
            vector2.Clear();
            Assert.AreEqual(false, vector.Equals(vector2));
        }

        // Exists, Find, FindAll, FindIndex, FindLast, FindLastIndex; using a predicate.
        // IndexOf, LastIndexOf; using an element.
        {
            var vector = new Vector<Int32>();
            Assert.AreEqual(false, vector.Exists(Is3));
            Assert.AreEqual(0, vector.Find(Is3));
            Vector<Int32> all = vector.FindAll(Is3);
            Assert.AreEqual(0, vector.Count);
            Assert.AreEqual(-1, vector.FindIndex(Is3));
            Assert.AreEqual(-1, vector.FindIndex(0, Is3));
            Assert.AreEqual(-1, vector.FindIndex(0, 0, Is3));
            Assert.AreEqual(0, vector.FindLast(Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(0, Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(0, 0, Is3));
            Assert.AreEqual(-1, vector.IndexOf(3));
            Assert.AreEqual(-1, vector.IndexOf(3, 0));
            Assert.AreEqual(-1, vector.IndexOf(3, 0, 0));
            Assert.AreEqual(-1, vector.LastIndexOf(3));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 0));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 0, 0));

            vector.Add(2);
            Assert.AreEqual(false, vector.Exists(Is3));
            Assert.AreEqual(0, vector.Find(Is3));
            all = vector.FindAll(Is3);
            Assert.AreEqual(0, all.Count);
            Assert.AreEqual(-1, vector.FindIndex(Is3));
            Assert.AreEqual(-1, vector.FindIndex(0, Is3));
            Assert.AreEqual(-1, vector.FindIndex(1, Is3));
            Assert.AreEqual(-1, vector.FindIndex(0, 1, Is3));
            Assert.AreEqual(0, vector.FindLast(Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(1, Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(1, 0, Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(1, 1, Is3));
            Assert.AreEqual(-1, vector.IndexOf(3));
            Assert.AreEqual(-1, vector.IndexOf(3, 0));
            Assert.AreEqual(-1, vector.IndexOf(3, 0, 1));
            Assert.AreEqual(-1, vector.LastIndexOf(3));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 1));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 1, 0));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 1, 1));

            vector.Add(3);
            Assert.AreEqual(true, vector.Exists(Is3));
            Assert.AreEqual(3, vector.Find(Is3));
            all = vector.FindAll(Is3);
            Assert.AreEqual(1, all.Count);
            Assert.AreEqual(3, all[0]);
            Assert.AreEqual(1, vector.FindIndex(Is3));
            Assert.AreEqual(1, vector.FindIndex(0, Is3));
            Assert.AreEqual(1, vector.FindIndex(1, Is3));
            Assert.AreEqual(-1, vector.FindIndex(2, Is3));
            Assert.AreEqual(-1, vector.FindIndex(0, 0, Is3));
            Assert.AreEqual(-1, vector.FindIndex(0, 1, Is3));
            Assert.AreEqual(1, vector.FindIndex(1, 1, Is3));
            Assert.AreEqual(-1, vector.FindIndex(1, 0, Is3));
            Assert.AreEqual(3, vector.FindLast(Is3));
            Assert.AreEqual(1, vector.FindLastIndex(Is3));
            Assert.AreEqual(1, vector.FindLastIndex(2, Is3));
            Assert.AreEqual(1, vector.FindLastIndex(1, Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(0, Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(2, 0, Is3));
            Assert.AreEqual(1, vector.FindLastIndex(2, 1, Is3));
            Assert.AreEqual(1, vector.IndexOf(3));
            Assert.AreEqual(1, vector.IndexOf(3, 0));
            Assert.AreEqual(-1, vector.IndexOf(3, 2));
            Assert.AreEqual(-1, vector.IndexOf(3, 1, 0));
            Assert.AreEqual(1, vector.IndexOf(3, 1, 1));
            Assert.AreEqual(1, vector.LastIndexOf(3));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 0));
            Assert.AreEqual(1, vector.LastIndexOf(3, 1));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 1, 0));
            Assert.AreEqual(1, vector.LastIndexOf(3, 1, 1));

            vector.Add(4);
            Assert.AreEqual(true, vector.Exists(Is3));
            Assert.AreEqual(3, vector.Find(Is3));
            all = vector.FindAll(Is3);
            Assert.AreEqual(1, all.Count);
            Assert.AreEqual(3, all[0]);
            Assert.AreEqual(1, vector.FindIndex(Is3));
            Assert.AreEqual(1, vector.FindIndex(1, Is3));
            Assert.AreEqual(-1, vector.FindIndex(2, Is3));
            Assert.AreEqual(-1, vector.FindIndex(3, Is3));
            Assert.AreEqual(-1, vector.FindIndex(0, 0, Is3));
            Assert.AreEqual(-1, vector.FindIndex(0, 1, Is3));
            Assert.AreEqual(1, vector.FindIndex(0, 2, Is3));
            Assert.AreEqual(3, vector.FindLast(Is3));
            Assert.AreEqual(1, vector.FindLastIndex(Is3));
            Assert.AreEqual(1, vector.FindLastIndex(3, Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(3, 0, Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(3, 1, Is3));
            Assert.AreEqual(1, vector.FindLastIndex(3, 2, Is3));
            Assert.AreEqual(1, vector.IndexOf(3));
            Assert.AreEqual(1, vector.IndexOf(3, 0));
            Assert.AreEqual(-1, vector.IndexOf(3, 2));
            Assert.AreEqual(-1, vector.IndexOf(3, 1, 0));
            Assert.AreEqual(1, vector.IndexOf(3, 1, 1));
            Assert.AreEqual(1, vector.LastIndexOf(3));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 0));
            Assert.AreEqual(1, vector.LastIndexOf(3, 1));
            Assert.AreEqual(1, vector.LastIndexOf(3, 2));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 3, 1));
            Assert.AreEqual(1, vector.LastIndexOf(3, 3, 2));

            vector.Add(3);
            Assert.AreEqual(true, vector.Exists(Is3));
            Assert.AreEqual(3, vector.Find(Is3));
            all = vector.FindAll(Is3);
            Assert.AreEqual(2, all.Count);
            Assert.AreEqual(3, all[0]);
            Assert.AreEqual(3, all[1]);
            Assert.AreEqual(1, vector.FindIndex(Is3));
            Assert.AreEqual(3, vector.FindIndex(2, Is3));
            Assert.AreEqual(3, vector.FindIndex(3, Is3));
            Assert.AreEqual(-1, vector.FindIndex(4, Is3));
            Assert.AreEqual(-1, vector.FindIndex(2, 1, Is3));
            Assert.AreEqual(3, vector.FindIndex(2, 2, Is3));
            Assert.AreEqual(3, vector.FindLast(Is3));
            Assert.AreEqual(3, vector.FindLastIndex(Is3));
            Assert.AreEqual(3, vector.FindLastIndex(4, Is3));
            Assert.AreEqual(3, vector.FindLastIndex(3, Is3));
            Assert.AreEqual(1, vector.FindLastIndex(2, Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(4, 0, Is3));
            Assert.AreEqual(3, vector.FindLastIndex(4, 1, Is3));
            Assert.AreEqual(3, vector.FindLastIndex(4, 4, Is3));
            Assert.AreEqual(1, vector.IndexOf(3));
            Assert.AreEqual(1, vector.IndexOf(3, 0));
            Assert.AreEqual(3, vector.IndexOf(3, 2));
            Assert.AreEqual(-1, vector.IndexOf(3, 2, 1));
            Assert.AreEqual(3, vector.IndexOf(3, 2, 2));
            Assert.AreEqual(3, vector.LastIndexOf(3));
            Assert.AreEqual(3, vector.LastIndexOf(3, 4));
            Assert.AreEqual(3, vector.LastIndexOf(3, 3));
            Assert.AreEqual(1, vector.LastIndexOf(3, 2));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 4, 0));
            Assert.AreEqual(3, vector.LastIndexOf(3, 4, 1));

            vector[1] = 0;
            Assert.AreEqual(true, vector.Exists(Is3));
            Assert.AreEqual(3, vector.Find(Is3));
            all = vector.FindAll(Is3);
            Assert.AreEqual(1, all.Count);
            Assert.AreEqual(3, all[0]);
            Assert.AreEqual(3, vector.FindIndex(Is3));
            Assert.AreEqual(3, vector.FindIndex(1, Is3));
            Assert.AreEqual(-1, vector.FindIndex(4, Is3));
            Assert.AreEqual(3, vector.FindIndex(0, 4, Is3));
            Assert.AreEqual(3, vector.FindLast(Is3));
            Assert.AreEqual(3, vector.FindLastIndex(Is3));
            Assert.AreEqual(3, vector.FindLastIndex(4, Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(2, Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(4, 0, Is3));
            Assert.AreEqual(3, vector.FindLastIndex(4, 1, Is3));
            Assert.AreEqual(3, vector.IndexOf(3));
            Assert.AreEqual(3, vector.IndexOf(3, 0));
            Assert.AreEqual(3, vector.IndexOf(3, 2, 2));
            Assert.AreEqual(3, vector.LastIndexOf(3));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 2));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 4, 0));
            Assert.AreEqual(3, vector.LastIndexOf(3, 4, 1));

            vector[3] = 0;
            Assert.AreEqual(false, vector.Exists(Is3));
            Assert.AreEqual(0, vector.Find(Is3));
            all = vector.FindAll(Is3);
            Assert.AreEqual(0, all.Count);
            Assert.AreEqual(-1, vector.FindIndex(Is3));
            Assert.AreEqual(-1, vector.FindIndex(1, Is3));
            Assert.AreEqual(-1, vector.FindIndex(4, Is3));
            Assert.AreEqual(-1, vector.FindIndex(0, 4, Is3));
            Assert.AreEqual(0, vector.FindLast(Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(4, Is3));
            Assert.AreEqual(-1, vector.FindLastIndex(4, 4, Is3));
            Assert.AreEqual(-1, vector.IndexOf(3));
            Assert.AreEqual(-1, vector.IndexOf(3, 0));
            Assert.AreEqual(-1, vector.IndexOf(3, 2, 2));
            Assert.AreEqual(-1, vector.LastIndexOf(3));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 2));
            Assert.AreEqual(-1, vector.LastIndexOf(3, 4, 4));
        }
        {
            var vector = new Vector<string>();
            Assert.AreEqual(false, vector.Exists(IsC));
            Assert.AreEqual(null, vector.Find(IsC));
            Vector<string> all = vector.FindAll(IsC);
            Assert.AreEqual(0, all.Count);
            Assert.AreEqual(-1, vector.FindIndex(IsC));
            Assert.AreEqual(-1, vector.FindIndex(0, IsC));
            Assert.AreEqual(-1, vector.FindIndex(0, 0, IsC));
            Assert.AreEqual(null, vector.FindLast(IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(0, IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(0, 0, IsC));
            Assert.AreEqual(-1, vector.IndexOf("C"));
            Assert.AreEqual(-1, vector.IndexOf("C", 0));
            Assert.AreEqual(-1, vector.IndexOf("C", 0, 0));
            Assert.AreEqual(-1, vector.LastIndexOf("C"));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 0));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 0, 0));

            vector.Add("B");
            Assert.AreEqual(false, vector.Exists(IsC));
            Assert.AreEqual(null, vector.Find(IsC));
            all = vector.FindAll(IsC);
            Assert.AreEqual(0, all.Count);
            Assert.AreEqual(-1, vector.FindIndex(IsC));
            Assert.AreEqual(-1, vector.FindIndex(0, IsC));
            Assert.AreEqual(-1, vector.FindIndex(1, IsC));
            Assert.AreEqual(-1, vector.FindIndex(0, 1, IsC));
            Assert.AreEqual(null, vector.FindLast(IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(1, IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(1, 0, IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(1, 1, IsC));
            Assert.AreEqual(-1, vector.IndexOf("C"));
            Assert.AreEqual(-1, vector.IndexOf("C", 0));
            Assert.AreEqual(-1, vector.IndexOf("C", 0, 1));
            Assert.AreEqual(-1, vector.LastIndexOf("C"));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 1));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 1, 0));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 1, 1));

            vector.Add("C");
            Assert.AreEqual(true, vector.Exists(IsC));
            Assert.AreEqual("C", vector.Find(IsC));
            all = vector.FindAll(IsC);
            Assert.AreEqual(1, all.Count);
            Assert.AreEqual("C", all[0]);
            Assert.AreEqual(1, vector.FindIndex(IsC));
            Assert.AreEqual(1, vector.FindIndex(0, IsC));
            Assert.AreEqual(1, vector.FindIndex(1, IsC));
            Assert.AreEqual(-1, vector.FindIndex(2, IsC));
            Assert.AreEqual(-1, vector.FindIndex(0, 0, IsC));
            Assert.AreEqual(-1, vector.FindIndex(0, 1, IsC));
            Assert.AreEqual(1, vector.FindIndex(1, 1, IsC));
            Assert.AreEqual(-1, vector.FindIndex(1, 0, IsC));
            Assert.AreEqual("C", vector.FindLast(IsC));
            Assert.AreEqual(1, vector.FindLastIndex(IsC));
            Assert.AreEqual(1, vector.FindLastIndex(2, IsC));
            Assert.AreEqual(1, vector.FindLastIndex(1, IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(0, IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(2, 0, IsC));
            Assert.AreEqual(1, vector.FindLastIndex(2, 1, IsC));
            Assert.AreEqual(1, vector.IndexOf("C"));
            Assert.AreEqual(1, vector.IndexOf("C", 0));
            Assert.AreEqual(-1, vector.IndexOf("C", 2));
            Assert.AreEqual(-1, vector.IndexOf("C", 1, 0));
            Assert.AreEqual(1, vector.IndexOf("C", 1, 1));
            Assert.AreEqual(1, vector.LastIndexOf("C"));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 0));
            Assert.AreEqual(1, vector.LastIndexOf("C", 1));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 1, 0));
            Assert.AreEqual(1, vector.LastIndexOf("C", 1, 1));

            vector.Add("D");
            Assert.AreEqual(true, vector.Exists(IsC));
            Assert.AreEqual("C", vector.Find(IsC));
            all = vector.FindAll(IsC);
            Assert.AreEqual(1, all.Count);
            Assert.AreEqual("C", all[0]);
            Assert.AreEqual(1, vector.FindIndex(IsC));
            Assert.AreEqual(1, vector.FindIndex(1, IsC));
            Assert.AreEqual(-1, vector.FindIndex(2, IsC));
            Assert.AreEqual(-1, vector.FindIndex(3, IsC));
            Assert.AreEqual(-1, vector.FindIndex(0, 0, IsC));
            Assert.AreEqual(-1, vector.FindIndex(0, 1, IsC));
            Assert.AreEqual(1, vector.FindIndex(0, 2, IsC));
            Assert.AreEqual("C", vector.FindLast(IsC));
            Assert.AreEqual(1, vector.FindLastIndex(IsC));
            Assert.AreEqual(1, vector.FindLastIndex(3, IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(3, 0, IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(3, 1, IsC));
            Assert.AreEqual(1, vector.FindLastIndex(3, 2, IsC));
            Assert.AreEqual(1, vector.IndexOf("C"));
            Assert.AreEqual(1, vector.IndexOf("C", 0));
            Assert.AreEqual(-1, vector.IndexOf("C", 2));
            Assert.AreEqual(-1, vector.IndexOf("C", 1, 0));
            Assert.AreEqual(1, vector.IndexOf("C", 1, 1));
            Assert.AreEqual(1, vector.LastIndexOf("C"));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 0));
            Assert.AreEqual(1, vector.LastIndexOf("C", 1));
            Assert.AreEqual(1, vector.LastIndexOf("C", 2));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 3, 1));
            Assert.AreEqual(1, vector.LastIndexOf("C", 3, 2));

            vector.Add("C");
            Assert.AreEqual(true, vector.Exists(IsC));
            Assert.AreEqual("C", vector.Find(IsC));
            all = vector.FindAll(IsC);
            Assert.AreEqual(2, all.Count);
            Assert.AreEqual("C", all[0]);
            Assert.AreEqual("C", all[1]);
            Assert.AreEqual(1, vector.FindIndex(IsC));
            Assert.AreEqual(3, vector.FindIndex(2, IsC));
            Assert.AreEqual(3, vector.FindIndex(3, IsC));
            Assert.AreEqual(-1, vector.FindIndex(4, IsC));
            Assert.AreEqual(-1, vector.FindIndex(2, 1, IsC));
            Assert.AreEqual(3, vector.FindIndex(2, 2, IsC));
            Assert.AreEqual("C", vector.FindLast(IsC));
            Assert.AreEqual(3, vector.FindLastIndex(IsC));
            Assert.AreEqual(3, vector.FindLastIndex(4, IsC));
            Assert.AreEqual(3, vector.FindLastIndex(3, IsC));
            Assert.AreEqual(1, vector.FindLastIndex(2, IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(4, 0, IsC));
            Assert.AreEqual(3, vector.FindLastIndex(4, 1, IsC));
            Assert.AreEqual(3, vector.FindLastIndex(4, 4, IsC));
            Assert.AreEqual(1, vector.IndexOf("C"));
            Assert.AreEqual(1, vector.IndexOf("C", 0));
            Assert.AreEqual(3, vector.IndexOf("C", 2));
            Assert.AreEqual(-1, vector.IndexOf("C", 2, 1));
            Assert.AreEqual(3, vector.IndexOf("C", 2, 2));
            Assert.AreEqual(3, vector.LastIndexOf("C"));
            Assert.AreEqual(3, vector.LastIndexOf("C", 4));
            Assert.AreEqual(3, vector.LastIndexOf("C", 3));
            Assert.AreEqual(1, vector.LastIndexOf("C", 2));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 4, 0));
            Assert.AreEqual(3, vector.LastIndexOf("C", 4, 1));

            vector[1] = string.Empty;
            Assert.AreEqual(true, vector.Exists(IsC));
            Assert.AreEqual("C", vector.Find(IsC));
            all = vector.FindAll(IsC);
            Assert.AreEqual(1, all.Count);
            Assert.AreEqual("C", all[0]);
            Assert.AreEqual(3, vector.FindIndex(IsC));
            Assert.AreEqual(3, vector.FindIndex(1, IsC));
            Assert.AreEqual(-1, vector.FindIndex(4, IsC));
            Assert.AreEqual(3, vector.FindIndex(0, 4, IsC));
            Assert.AreEqual("C", vector.FindLast(IsC));
            Assert.AreEqual(3, vector.FindLastIndex(IsC));
            Assert.AreEqual(3, vector.FindLastIndex(4, IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(2, IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(4, 0, IsC));
            Assert.AreEqual(3, vector.FindLastIndex(4, 1, IsC));
            Assert.AreEqual(3, vector.IndexOf("C"));
            Assert.AreEqual(3, vector.IndexOf("C", 0));
            Assert.AreEqual(3, vector.IndexOf("C", 2, 2));
            Assert.AreEqual(3, vector.LastIndexOf("C"));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 2));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 4, 0));
            Assert.AreEqual(3, vector.LastIndexOf("C", 4, 1));

            vector[3] = string.Empty;
            Assert.AreEqual(false, vector.Exists(IsC));
            Assert.AreEqual(null, vector.Find(IsC));
            all = vector.FindAll(IsC);
            Assert.AreEqual(0, all.Count);
            Assert.AreEqual(-1, vector.FindIndex(IsC));
            Assert.AreEqual(-1, vector.FindIndex(1, IsC));
            Assert.AreEqual(-1, vector.FindIndex(4, IsC));
            Assert.AreEqual(-1, vector.FindIndex(0, 4, IsC));
            Assert.AreEqual(null, vector.FindLast(IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(4, IsC));
            Assert.AreEqual(-1, vector.FindLastIndex(4, 4, IsC));
            Assert.AreEqual(-1, vector.IndexOf("C"));
            Assert.AreEqual(-1, vector.IndexOf("C", 0));
            Assert.AreEqual(-1, vector.IndexOf("C", 2, 2));
            Assert.AreEqual(-1, vector.LastIndexOf("C"));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 2));
            Assert.AreEqual(-1, vector.LastIndexOf("C", 4, 4));
        }

        // ForEach.
        for (Int32 test = 0; test != 10; test++)
        {
            var vector = new Vector<Int32>();
            Int32 sum = 0;
            while (rng.Next(5) != 0)
            {
                Int32 element = rng.Next(10);
                vector.Add(element);
                sum += element;
            }
            _int32Element = 0;
            vector.ForEach(Sum);
            Assert.AreEqual(_int32Element, sum);
        }

        // GetRange.
        for (Int32 test = 0; test != 10; test++)
        {
            var vector = new Vector<Int32>();
            int count = rng.Next(10);
            for (int i = 0; i != count; i++)
            {
                vector.Add(rng.Next());
            }
            int rangeIndex = rng.Next(count + 1);
            int rangeCount = rangeIndex == count? 0: rng.Next(count - rangeIndex);
            Vector<Int32> range = vector.GetRange(rangeIndex, rangeCount);
            Assert.AreEqual(rangeCount, range.Count);
            for (int i = 0; i != rangeCount; i++)
            {
                Assert.AreEqual(vector[rangeIndex + i], range[i]);
            }
        }

        // InsertRange.
        for (Int32 test = 0; test != 10; test++)
        {
            var from = new Vector<Int32>();
            int fromCount = rng.Next(10);
            for (int i = 0; i != fromCount; i++)
            {
                from.Add(rng.Next());
            }
            var to = new Vector<Int32>();
            int toCount = rng.Next(10);
            Int32 toElement = rng.Next();
            for (int i = 0; i != toCount; i++)
            {
                to.Add(toElement);
            }
            int toIndex = rng.Next(toCount + 1);
            to.InsertRange(toIndex, from);
            Assert.AreEqual(toCount + fromCount, to.Count);
            for (int i = 0; i != toIndex; i++)
            {
                Assert.AreEqual(toElement, to[i]);
            }
            for (int i = 0; i != fromCount; i++)
            {
                Assert.AreEqual(from[i], to[toIndex + i]);
            }
            for (int i = 0; i != to.Count - toIndex - fromCount; i++)
            {
                Assert.AreEqual(toElement, to[toIndex + fromCount + i]);
            }
        }

        // RemoveAll.
        for (Int32 test = 0; test != 10; test++)
        {
            var vector = new Vector<Int32>();
            Assert.AreEqual(0, vector.RemoveAll(Is3));
            int count = 0;
            for (Int32 i = 0; i != 10; i++)
            {
                Int32 element = rng.Next(10);
                vector.Add(element);
                if (element == 3)
                {
                    count++;
                }
            }
            Assert.AreEqual(count, vector.RemoveAll(Is3));
        }

        // RemoveRange.
        for (Int32 test = 0; test != 10; test++)
        {
            var vector = new Vector<Int32>();
            int count = rng.Next(10);
            for (Int32 element = 0; element != count; element++)
            {
                vector.Add(element);
            }
            int rangeIndex = rng.Next(count + 1);
            int rangeCount = rng.Next(count - rangeIndex + 1);
            vector.RemoveRange(rangeIndex, rangeCount);
            Assert.AreEqual(count - rangeCount, vector.Count);
            for (int i = 0; i != vector.Count; i++)
            {
                if (i < rangeIndex)
                {
                    Assert.AreEqual(i, vector[i]);
                }
                else
                {
                    Assert.AreEqual(i + rangeCount, vector[i]);
                }
            }
        }

        // Reverse.
        for (Int32 test = 0; test != 10; test++)
        {
            var vector = new Vector<Int32>();
            int count = rng.Next(10);
            for (Int32 element = 0; element != count; element++)
            {
                vector.Add(element);
            }
            vector.Reverse();
            Assert.AreEqual(count, vector.Count);
            for (int i = 0; i != count; i++)
            {
                Assert.AreEqual(count - i - 1, vector[i]);
            }
            vector.Reverse();
            int rangeIndex = rng.Next(count + 1);
            int rangeCount = rng.Next(count - rangeIndex + 1);
            vector.Reverse(rangeIndex, rangeCount);
            for (int i = 0; i != count; i++)
            {
                if (i < rangeIndex || i >= rangeIndex + rangeCount)
                {
                    Assert.AreEqual(i, vector[i]);
                }
                else
                {
                    Assert.AreEqual(rangeCount - i - 1 + 2 * rangeIndex, vector[i]);
                }
            }
        }

        // Sort.
        for (Int32 test = 0; test != 10; test++)
        {
            const Int32 ValueRange = 20;
            const Int32 CountRange = 30;
            var intList = new List<Int32>();
            var stringList = new List<string>();
            var int32Vector = new Vector<Int32>();
            var stringVector = new Vector<string>();
            int count = rng.Next(CountRange);
            for (int i = 0; i != count; i++)
            {
                Int32 element = rng.Next(ValueRange);
                intList.Add(element);
                stringList.Add(element.ToString());
                int32Vector.Add(element);
                stringVector.Add(element.ToString());
            }
            intList.Sort();
            stringList.Sort();
            int32Vector.Sort();
            stringVector.Sort();
            for (int i = 0; i != count; i++)
            {
                Assert.AreEqual(intList[i], int32Vector[i]);
                Assert.AreEqual(stringList[i], stringVector[i]);
            }
            Assert.AreEqual(true, int32Vector.GetConsistency());
            Assert.AreEqual(true, stringVector.GetConsistency());
        }

        // Culture awareness of Sort.
        {
            var list = new List<string>();
            list.Add("Apple");
            list.Add("Æble");
            var vector = new Vector<string>();
            vector.Add("Apple");
            vector.Add("Æble");
            CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
            Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("da-DK");
            list.Sort();
            vector.Sort();
            Assert.AreEqual(list[0], vector[0]);
            Assert.AreEqual(list[1], vector[1]);
            Assert.AreEqual("Apple", vector[0]);
            Assert.AreEqual("Æble", vector[1]);
            Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
            list.Sort();
            vector.Sort();
            Assert.AreEqual(list[0], vector[0]);
            Assert.AreEqual(list[1], vector[1]);
            Assert.AreEqual("Æble", vector[0]);
            Assert.AreEqual("Apple", vector[1]);
            Thread.CurrentThread.CurrentCulture = currentCulture;
            Assert.AreEqual(true, vector.GetConsistency());
        }

        // Sort, using a comparer.
        for (Int32 test = 0; test != 10; test++)
        {
            var vector = new Vector<Int32>();
            int count = rng.Next(10);
            for (int i = 0; i != count; i++)
            {
                vector.Add(rng.Next(10));
            }
            vector.Sort(new DescIntComparer());
            Assert.AreEqual(count, vector.Count);
            for (int i = 1; i < count; i++)
            {
                Assert.AreEqual(true, vector[i - 1] >= vector[i]);
            }
        }

        // Sort a range, using a comparer.
        for (Int32 test = 0; test != 10; test++)
        {
            var vector = new Vector<Int32>();
            int count = rng.Next(20);
            for (int i = 0; i != count; i++)
            {
                vector.Add(rng.Next(20));
            }
            var vector2 = new Vector<Int32>(vector);
            int rangeIndex = rng.Next(count + 1);
            int rangeCount = rng.Next(count - rangeIndex + 1);
            vector.Sort(rangeIndex, rangeCount, new DescIntComparer());
            Assert.AreEqual(count, vector.Count);
            for (int i = 0; i != count; i++)
            {
                if (i < rangeIndex || i >= rangeIndex + rangeCount)
                {
                    Assert.AreEqual(vector2[i], vector[i]);
                }
                else
                {
                    if (i != rangeIndex)
                    {
                        Assert.AreEqual(true, vector[i - 1] >= vector[i]);
                    }
                }
            }
        }

        // ToArray.
        for (Int32 test = 0; test != 10; test++)
        {
            int count = rng.Next(10);
            var vector = new Vector<Int32>();
            for (int i = 0; i != count; i++)
            {
                vector.Add(rng.Next());
            }
            Int32[] array = vector.ToArray();
            Assert.AreEqual(count, array.Length);
            for (int i = 0; i != count; i++)
            {
                Assert.AreEqual(vector[i], array[i]);
            }
        }

        // ToString. Expect the fully qualified name, for example Lemody.Glu.Vector`1[System.Int32].
        {
            var vector = new Vector<Int32>();
            string toString = vector.ToString();
            Assert.AreNotEqual(true, string.IsNullOrEmpty(toString));
            string[] parts = toString.Split('.');
            Assert.AreEqual(true, parts.Length > 2);
            Assert.AreEqual("Vector`1[System", parts[parts.Length - 2]);
            Assert.AreEqual("Int32]", parts[parts.Length - 1]);
        }

        // TrueForAll.
        for (Int32 test = 0; test != 10; test++)
        {
            int count = rng.Next(10);
            var vector = new Vector<Int32>();
            bool all3 = true;
            for (int i = 0; i != count; i++)
            {
                Int32 element = 1 + rng.Next(3);
                vector.Add(element);
                if (element != 3)
                {
                    all3 = false;
                }
            }
            Assert.AreEqual(all3, vector.TrueForAll(Is3));
        }
    }

    /// <summary>Updates the factors such that the multiplication of the factors yields the next count.</summary>
    /// <remarks>
    ///     If the factors are initialized with (1, 1) this method returns (2, 1), (5, 1), (1, 10), (2, 10) etc. When
    ///     multiplied this results in 2, 5, 10, 20, 50, 100 etc.
    /// </remarks>
    /// <param name="factor1">IO: Factor 1. Initialize with 1, 2 or 5.</param>
    /// <param name="factor2">IO: Factor 2. Initialize with 100, 1.000, 10.000 etc.</param>
    private static void NextFactors(ref Int32 factor1, ref Int32 factor2)
    {
        if (factor1 == 1)
        {
            factor1 = 2;
        }
        else if (factor1 == 2)
        {
            factor1 = 5;
        }
        else
        {
            Debug.Assert(factor1 == 5);
            factor1 = 1;
            factor2 *= 10;
        }
        Assert.AreEqual(true, factor1 * factor2 > 0);
    }

    /// <summary>Compares the vector performance to the list performance.</summary>
    [TestMethod]
    public void VectorPerformance()
    {
        Random rng = Rng(MethodInfo.GetCurrentMethod());
        const Int32 overallSeconds = DurationPerformanceTests;
        const Int32 ValueRange = 1000000;
        var overall = new Stopwatch();
        overall.Start();
        Int32 factor1 = 1;
        Int32 factor2 = 1000;
        bool doVector = rng.Next() % 2 == 0;
        while (overall.Elapsed.TotalSeconds < overallSeconds)
        {
            int count = factor1 * factor2;
            var list = new List<Int32>();
            var vector = new Vector<Int32>();
            Int64 listMs = 0;
            Int64 vectorMs = 0;
            for (Int32 collection = 0; collection != 2; collection++)
            {
                var stopwatch = new Stopwatch();
                stopwatch.Start();
                doVector = !doVector;
                Int32 actualCount = 0;
                while (actualCount != count)
                {
                    Int32 action = rng.Next(7);
                    if (action == 0 && actualCount != 0)
                    {
                        int index = rng.Next(actualCount);
                        if (doVector)
                        {
                            vector.RemoveAt(index);
                        }
                        else
                        {
                            list.RemoveAt(index);
                        }
                        actualCount--;
                    }
                    else
                    {
                        Int32 element = rng.Next(ValueRange);
                        if (action == 0 || action == 1 || action == 2)
                        {
                            if (doVector)
                            {
                                vector.Add(element);
                            }
                            else
                            {
                                list.Add(element);
                            }
                        }
                        else if (action == 3 || action == 4)
                        {
                            if (doVector)
                            {
                                vector.Insert(0, element);
                            }
                            else
                            {
                                list.Insert(0, element);
                            }
                        }
                        else
                        {
                            Debug.Assert(action == 5 || action == 6);
                            int index = actualCount == 0? 0: rng.Next(actualCount);
                            if (doVector)
                            {
                                vector.Insert(index, element);
                            }
                            else
                            {
                                list.Insert(index, element);
                            }
                        }
                        actualCount++;
                    }
                }
                if (doVector)
                {
                    Int64 total = 0;
                    for (int i = 0; i != count; i++)
                    {
                        vector[i]++;
                        total += vector[i];
                    }
                    foreach (Int32 element in vector)
                    {
                        total -= element;
                    }
                    Assert.AreEqual(0, total);
                }
                else
                {
                    Int64 total = 0;
                    for (int i = 0; i != count; i++)
                    {
                        list[i]++;
                        total += list[i];
                    }
                    foreach (Int32 element in list)
                    {
                        total -= element;
                    }
                    Assert.AreEqual(0, total);
                }
                while (actualCount != 0)
                {
                    Int32 action = rng.Next(3);
                    if (action == 0)
                    {
                        if (doVector)
                        {
                            vector.RemoveAt(0);
                        }
                        else
                        {
                            list.RemoveAt(0);
                        }
                    }
                    else if (action == 1)
                    {
                        if (doVector)
                        {
                            vector.RemoveAt(actualCount - 1);
                        }
                        else
                        {
                            list.RemoveAt(actualCount - 1);
                        }
                    }
                    else
                    {
                        Debug.Assert(action == 2);
                        int index = rng.Next(actualCount);
                        if (doVector)
                        {
                            vector.RemoveAt(index);
                        }
                        else
                        {
                            list.RemoveAt(index);
                        }
                    }
                    actualCount--;
                }
                if (doVector)
                {
                    vectorMs = stopwatch.ElapsedMilliseconds;
                }
                else
                {
                    listMs = stopwatch.ElapsedMilliseconds;
                }
            }
            Trace.WriteLine(string.Format("{0} elements list {1} ms vector {2} ms", count, listMs, vectorMs));
            NextFactors(ref factor1, ref factor2);
        }
    }

    /// <summary>Compares the vector sort performance to the list sort performance.</summary>
    [TestMethod]
    public void VectorSortPerformance()
    {
        Random rng = Rng(MethodInfo.GetCurrentMethod());
        const Int32 overallSeconds = DurationPerformanceTests;
        const Int32 ValueRange = 1000000;
        var overall = new Stopwatch();
        overall.Start();
        Int32 factor1 = 1;
        Int32 factor2 = 1000;
        bool doVector = rng.Next() % 2 == 0;
        while (overall.Elapsed.TotalSeconds < overallSeconds)
        {
            int count = factor1 * factor2;
            var list = new List<Int32>();
            var vector = new Vector<Int32>();
            Int64 listMs = 0;
            Int64 vectorMs = 0;
            for (Int32 collection = 0; collection != 2; collection++)
            {
                doVector = !doVector;
                for (int i = 0; i != count; i++)
                {
                    Int32 element = rng.Next(ValueRange);
                    if (doVector)
                    {
                        vector.Add(element);
                    }
                    else
                    {
                        list.Add(element);
                    }
                }
                var stopwatch = new Stopwatch();
                stopwatch.Start();
                if (doVector)
                {
                    vector.Sort();
                    vectorMs = stopwatch.ElapsedMilliseconds;
                }
                else
                {
                    list.Sort();
                    listMs = stopwatch.ElapsedMilliseconds;
                }
            }
            Trace.WriteLine(string.Format("{0} elements sorted, list {1} ms vector {2} ms", count, listMs, vectorMs));
            NextFactors(ref factor1, ref factor2);
        }
    }

    /// <summary>Compares the vector binary search performance to the list binary search performance.</summary>
    [TestMethod]
    public void VectorBinarySearchPerformance()
    {
        Random rng = Rng(MethodInfo.GetCurrentMethod());
        const Int32 overallSeconds = DurationPerformanceTests;
        const Int32 ValueRange = 5;
        var overall = new Stopwatch();
        overall.Start();
        Int32 factor1 = 1;
        Int32 factor2 = 1000;
        bool doVector = rng.Next() % 2 == 0;
        while (overall.Elapsed.TotalSeconds < overallSeconds)
        {
            int count = factor1 * factor2;
            var list = new List<Int64>();
            var vector = new Vector<Int64>();
            Int64 listMs = 0;
            Int64 vectorMs = 0;
            for (Int32 collection = 0; collection != 2; collection++)
            {
                doVector = !doVector;
                Int64 element = 0;
                for (int i = 0; i != count; i++)
                {
                    element += rng.Next(ValueRange);
                    if (doVector)
                    {
                        vector.Add(element);
                    }
                    else
                    {
                        list.Add(element);
                    }
                }
                Int32 maxValue = (Int32) Math.Min(element, Int32.MaxValue);
                var stopwatch = new Stopwatch();
                stopwatch.Start();
                if (doVector)
                {
                    for (int i = 0; i != count; i++)
                    {
                        Int64 searchValue = rng.Next(maxValue);
                        int index = vector.BinarySearch(searchValue);
                    }
                    vectorMs = stopwatch.ElapsedMilliseconds;
                }
                else
                {
                    for (int i = 0; i != count; i++)
                    {
                        Int64 searchValue = rng.Next(maxValue);
                        int index = list.BinarySearch(searchValue);
                    }
                    listMs = stopwatch.ElapsedMilliseconds;
                }
            }
            Trace.WriteLine(string.Format("{0} elements searched, list {1} ms vector {2} ms", count, listMs, vectorMs));
            NextFactors(ref factor1, ref factor2);
        }
    }

    /// <summary>Tests the vector support in addition to the support in line with the generic collections and list.</summary>
    [TestMethod]
    public void VectorAdditions()
    {
        Random rng = Rng(MethodInfo.GetCurrentMethod());

        // Iterate using vector nodes.
        for (Int32 test = 0; test != 10; test++)
        {
            var vector = new Vector<Int32>();
            int count = rng.Next(20);
            for (int index = 0; index != count; index++)
            {
                vector.Add(rng.Next());
            }
            VectorNode<Int32> node = vector.GetFirstNode();
            for (int index = 0; index != count; index++)
            {
                Assert.AreNotEqual(null, node);
                Assert.AreEqual(vector[index], node.Element);
                node = node.GetNext();
            }
            Assert.AreEqual(null, node);
            node = vector.GetLastNode();
            for (int index = count - 1; index >= 0; index--)
            {
                Assert.AreNotEqual(null, node);
                Assert.AreEqual(vector[index], node.Element);
                node = node.GetPrevious();
            }
            Assert.AreEqual(null, node);
        }
    }
}

/// <summary>Test support class to compare ints, resulting in a descending order.</summary>
class DescIntComparer: IComparer<Int32>
{
    /// <summary>Compare method for the test, resulting in a descending order of compared ints.</summary>
    /// <param name="first">I: First element in the compare.</param>
    /// <param name="second">I: Second element in the compare.</param>
    /// <returns></returns>
    public Int32 Compare(Int32 first, Int32 second)
    {
        return first < second? 1: first > second? -1: 0;
    }
}

}
